package com.hxzy.rediskeyexpired.config;

import com.hxzy.rediskeyexpired.controller.OrderController;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 *监听rdis的key过期后的回调监听事件
 * 需要在redis.conf配置  notify-keyspace-events Ex
 */
@Log4j2
@Component
public class RedisKeyExpiredListener extends KeyExpirationEventMessageListener {
    /**
     * Creates new {@link MessageListener} for {@code __keyevent@*__:expired} messages.
     *
     * @param listenerContainer must not be {@literal null}.
     */
    public RedisKeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }


    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String key = message.toString();
        log.info(key+"过期了.....");


        if (key.startsWith(OrderController.TEMP_PAY_KEY)) {
            int index = key.lastIndexOf(OrderController.TEMP_PAY_KEY + 1);
            //订单编号
            String orderId = key.substring(index);
            //查询数据库的值
            String redisKey = OrderController.CREATE_ORDER_KEY + orderId;

            //加入分布式锁（最简单的，最不可靠的）
            String lockKey = "lock:order:" + orderId;
            try {
                if (!this.redisTemplate.opsForValue().setIfAbsent(lockKey, 0, 60, TimeUnit.SECONDS)) {
                   log.error("多线程操作同一笔订单，加锁不成功，释放订单无效");
                }


                Object redisValue = this.redisTemplate.opsForValue().get(redisKey);
                if (Objects.nonNull(redisValue)) {
                    //取消订单
                    Map<String, Object> map = (Map<String, Object>) redisValue;

                    if (map.get("pay").equals(0)) {
                        log.info("----取消订单---");
                        //取消订单
                        this.redisTemplate.delete(redisKey);
                    }
                }
            }finally {
                this.redisTemplate.delete(lockKey);
            }
        }
    }
}
